#include "arraylist.h"
#include <string.h>
#include <assert.h>
//#include <stdio.h>

// allocation and initialization
ArrayList::ArrayList()
{
    _nInitialCapacity=INITIAL_CAPACITY;
    clear();
}

ArrayList::ArrayList(int initialCapacity)
{
    _nInitialCapacity=initialCapacity;
    clear();
}

void ArrayList:: clear(){
    assert(_nInitialCapacity>0);

    _values=new T[_nInitialCapacity];
    _nSize=0;
}

//deallocation 
ArrayList::~ArrayList()
{
    if(_values!=NULL)
	delete _values;
}

/// real realization starts here
/*
 * Method to ensure the size of our array can store capacity 
 * elements
 !param capacity the size of the array needed to support
 */
void ArrayList:: ensureCapacity(int capacity)
{
    if(capacity > _nInitialCapacity){
	T* newArray=new T[capacity + capacity/2];

	for(int i=0; i<_nSize; i++)
	    newArray[i]=_values[i];
	_nInitialCapacity=capacity + capacity/2;
	delete _values;
	_values=newArray;
    }
}


void ArrayList::insert(T value, int where)
{
   //printf("The size of our array is %d; where we would like to insert: %d\n", _nSize, where);
   assert(where>=0 && where<=_nSize);

   ensureCapacity(_nSize+1);
   for(int i=_nSize-1; i>where; i--)
       _values[i+1]=_values[i];
   _values[where]=value;
   ++_nSize;
}


void ArrayList::add(T value)
{
    insert(value,_nSize);
}

bool ArrayList::isOutOfBounds(int index)
{
    if(index<0 || index>=_nSize)
	return true;
    
    return false;
}


T ArrayList:: get(int index)
{
    /*
    printf("The index of our element is %d; array's size: %d\n", index, _nSize);
    printf("The index is out of bounds:%d\n", isOutOfBounds(index)?1:0);
    */
    assert(!isOutOfBounds(index));

    return _values[index];
}


int ArrayList:: indexOf(T value)
{
    for(int i=0; i<_nSize; i++)
	if(_values[i]==value)
	    return i;
    return -1;
}
 
T ArrayList:: deleteElement(int index)
{
    assert(!isOutOfBounds(index));

    T value=_values[index];
    for(int i=index; i<_nSize-1; i++)
        _values[i]=_values[i+1];
    _nSize--;

    return value;
}


int ArrayList:: deleteElementWithValue(T value)
{
    int out=indexOf(value);
    if(!isOutOfBounds(out))
	deleteElement(out);

    return out;
}

int ArrayList:: size()
{
    return _nSize;
}


bool ArrayList:: isEmpty()
{
    return _nSize==0;
}

void ArrayList:: startPos()
{
    _nCur=0;
}

bool ArrayList:: isAtEnd()
{
    return (_nCur==_nSize-1);
}

T ArrayList:: getNext()
{
    assert(!isOutOfBounds(_nCur));

    return _values[_nCur++];
}

void ArrayList:: deleteAll()
{
    _nSize=0;
}
